/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.sonar.util.sync;

import bgu.sonar.util.ex.UncheckedInterruptedException;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
import org.openide.util.Exceptions;

/**
 * for singletones stored in a map that can be accessed from multiple threads
 *
 * @author bennyl
 */
public abstract class MTMapSingleton<K, V> {

    private K k;
    private Semaphore takeLock = new Semaphore(1);

    public MTMapSingleton(K k) {
        this.k = k;
    }

    public V get(ConcurrentMap<K, V> from) {
        V res = from.get(k);
        if (res == null) {
            try {
                takeLock.acquire();
                res = from.get(k);
                if (res == null) {
                    res = create();
                    from.put(k, res);
                }
            } catch (InterruptedException ex) {
                throw new UncheckedInterruptedException(ex);
            } finally {
                takeLock.release();
            }
        }

        return res;
    }

    protected abstract V create();
}
